<template>
  <div class="box">
    <el-form :model="filmFormData" :rules="rules" ref="filmFormRef" label-width="100px">
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="电影名称" prop="name">
            <el-input v-model="filmFormData.name"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="电影导演" prop="director">
            <el-input v-model="filmFormData.director"></el-input>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="电影片长" prop="movie_long">
            <el-input-number v-model.number="filmFormData.movie_long"></el-input-number>
            <span> 分钟</span>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="综合评分" prop="score">
            <el-input-number
              :precision="1"
              :step="0.1"
              :max="10"
              :min="1"
              v-model.number="filmFormData.score"
            ></el-input-number>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="想看人数" prop="wish_num">
            <el-input-number :step="1000" v-model.number="filmFormData.wish_num"></el-input-number>
            <span> 人</span>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="电影语言" prop="language">
            <el-select v-model="filmFormData.language" placeholder="请选择">
              <el-option label="国语" value="国语"> </el-option>
              <el-option label="粤语" value="粤语"> </el-option>
              <el-option label="英语" value="英语"> </el-option>
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="电影类型" prop="type">
            <el-select v-model="filmFormData.type" placeholder="请选择">
              <el-option label="动作片" value="动作片"> </el-option>
              <el-option label="喜剧片" value="喜剧片"> </el-option>
              <el-option label="爱情片" value="爱情片"> </el-option>
              <el-option label="科幻片" value="科幻片"> </el-option>
              <el-option label="悬疑片" value="悬疑片"> </el-option>
              <el-option label="恐怖片" value="恐怖片"> </el-option>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="上映时间" prop="public_date">
            <el-date-picker
              v-model="filmFormData.public_date"
              value-format="yyyy-MM-dd"
              type="date"
              placeholder="选择日期"
            >
            </el-date-picker>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="电影海报" prop="poster">
            <el-upload
              drag
              action=""
              :multiple="false"
              :show-file-list="false"
              :before-upload="onUploadPoster"
              accept=".jpg,.jpeg,.png,.gif"
            >
              <i class="el-icon-upload"></i>
              <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
              <div class="el-upload__tip" slot="tip">只能上传jpg/png/gif文件，且不超过10MB</div>
            </el-upload>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <!-- <el-image :src="poster" style="width: 260px"></el-image> -->
          <img :src="poster" style="width: 260px" />
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="电影预告" prop="video">
            <el-upload
              drag
              action=""
              :multiple="false"
              :show-file-list="false"
              :before-upload="onUploadVideo"
              accept=".mp4,.wmv,.mov,.avi"
            >
              <i class="el-icon-upload"></i>
              <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
              <div class="el-upload__tip" slot="tip">只能上传.mp4,.wmv,.mov,.avi文件,最大100MB</div>
            </el-upload>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <!-- 视频播放 -->
          <video :poster="poster" controls :src="video" style="width: 260px"></video>
          <!-- <video ref="myvideoRef" style="width: 100%; height: 100%" class="video-js"></video> -->
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="24">
          <!-- 动态表单 -->
          <el-form-item
            v-for="(actor, index) in filmFormData.actor"
            :label="'演员' + (index === 0 ? '' : index)"
            :key="index"
            :prop="'actor.' + index + '.value'"
            :rules="{
              required: true,
              message: '演员名称不能为空',
              trigger: 'blur'
            }"
          >
            <el-input v-model="actor.value" style="width: 300px"></el-input>
            <span style="margin-left: 10px">
              <el-button v-if="index === 0" type="primary" @click.prevent="addActor">
                新增
              </el-button>
              <el-button v-else @click.prevent="removeActor(index)">删除</el-button>
            </span>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="24">
          <el-form-item label="电影简介" prop="intro">
            <!-- <el-input type="textarea" :rows="5" resize="none" v-model="filmFormData.intro" /> -->
            <div style="border: 1px solid #ccc">
              <Toolbar
                style="border-bottom: 1px solid #ccc"
                :editor="editor"
                :defaultConfig="toolbarConfig"
                :mode="mode"
              />
              <Editor
                style="height: 300px; overflow-y: hidden"
                v-model="filmFormData.intro"
                :defaultConfig="editorConfig"
                :mode="mode"
                @onCreated="onCreated"
              />
            </div>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-form-item>
          <el-button type="primary" @click="submitForm">新增电影信息</el-button>
          <el-button @click="resetForm">重置</el-button>
        </el-form-item>
      </el-row>
    </el-form>
  </div>
</template>

<script>
import { getFullYearDay, fileContentToHash, delay } from '@/utils/tools'
import formValidateMixin from './mixin'
import { uploadFilmPosterApi, uploadChunkVideoApi, mergeVideoApi } from '@/api/filmApi'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'

export default {
  mixins: [formValidateMixin],
  components: { Editor, Toolbar },
  data() {
    return {
      poster: 'http://localhost:9000/users/1698218428714_3535ae6a.jpg',
      video: '',
      filmFormData: {
        name: '',
        director: '',
        movie_long: 120,
        score: 10.0,
        wish_num: 300000,
        language: '国语',
        type: '',
        public_date: getFullYearDay(7, 'day')[0],
        actor: [
          {
            value: ''
          }
        ],
        intro: '',
        video: '',
        poster: ''
      },
      editor: null,
      toolbarConfig: {},
      editorConfig: { placeholder: '请输入内容...' },
      mode: 'default' // or 'simple'
    }
  },
  methods: {
    // 富文本
    onCreated(editor) {
      this.editor = Object.seal(editor) // 一定要用 Object.seal() ，否则会报错
    },
    // 海报图片上传处理操作
    async onUploadPoster(file) {
      // this.poster = URL.createObjectURL(file)
      // 限制上传图片只能小于或等一载10mb
      if (file.size > 1024 * 1024 * 10) {
        this.$message({
          message: '当前上传的图片过大,超过10MB',
          type: 'error',
          showClose: true,
          duration: 3000
        })
        return false
      }

      // 限制上传图片只能是图片
      let allowImage = ['image/jpeg', 'image/gif', 'image/png']
      const isType = allowImage.includes(file.type)
      if (!isType) {
        this.$message({
          message: '当前上传的图片是一个不合法的文件,只能上传图片',
          type: 'error',
          showClose: true,
          duration: 3000
        })
        return false
      }

      // 上传图片 FormData
      const formData = new FormData()
      formData.append('file', file)
      const ret = await uploadFilmPosterApi(formData)
      if (ret.code === 0) {
        this.filmFormData.poster = ret.data.path
        this.poster = ret.data.url
      }
      return false
    },
    // 预告视频上传处理操作
    // 预告片它的文件大小可能会很大，而服务器单个请求可能只能接受2M左右，此时就可以上传不成功了
    // 此时就需要进行把文件拆分成若干个小的文件，然后进行上传处理
    // 大文件上传的方案
    //  + 固定数量，进行拆分文件，数量固定，但单个拆分的文件大小不固定
    //  + 固定文件大小，进行拆分文件，单个拆分的文件大小固定，但数量不固定
    // 拆分后的文件，如果在后台中进行组合成一个完整的文件呢？
    //  + 拆分之前后给当前的文件按内容进行一次hash运算得到一个唯一字符串，此字符串就是此文件在标识，然后在给拆分的小块进行编写 aabeewf_1,aabeewf_2,aabeewf_3
    //   FileReader  spark-md5库
    //   File对象能不能进行切割？ 能，它也是继承了Blob块，它里面有一个slice方法，专门用来切割的
    // 上传之前可以进行验证，是否可上传 ping过程,它就是把文件切一个很小很小的片，可以是1kb左右，进行尝试上传，如果成功表示，可以继续上传，这样可确保上传的成功率。
    async onUploadVideo(file) {
      // 上传视图不能超过100mb
      if (file.size > 1024 * 1024 * 100) {
        this.$message({
          message: '当前上传的视频过大,超过100MB',
          type: 'error',
          showClose: true,
          duration: 3000
        })
        return false
      }
      // 上传只能上传.mp4,.wmv,.mov,.avi文件格式
      if (!['video/mp4', 'video/wmv', 'video/avi'].includes(file.type)) {
        this.$message({
          message: '当前上传的视频是一个不合法的文件,只能上传.mp4,.wmv,.mov,.avi文件格式',
          type: 'error',
          showClose: true,
          duration: 3000
        })
        return false
      }

      // 进行大文件上传操作处理，按固定数量进行拆分上传
      // 拆分的数量为5块
      const partNum = 5
      // 计算每块它的大小
      const partSize = file.size / partNum
      // https://www.jianshu.com/p/b89634e4eb3b
      // 按文件内容进行计算出来的hash值，用于上传后文件所用
      // npm i -S spark-md5
      // const reader = new FileReader()
      // reader.readAsArrayBuffer(file)
      // reader.onload = e => {
      //   let fileData = e.target.result
      //   const sparkMd5 = new SparkMd5.ArrayBuffer()
      //   sparkMd5.append(fileData)
      //   console.log(sparkMd5.end())
      // }
      // 根据文件内容生成对应的hash值，用于上传所用
      // 可以做秒传
      const hash = await fileContentToHash(file)
      // 获取扩展名
      const extname = file.name.slice(file.name.lastIndexOf('.'))

      // 进行文件切割
      const chunkFiles = []
      const chunkNames = []
      for (let i = 0; i < partNum; i++) {
        let start = i * partSize
        let end = start + partSize
        chunkFiles.push(file.slice(start, end))
        chunkNames.push(hash + '_' + i + extname)
      }

      // formData进行上传方式
      // 一次性全上传完，还是一个个的上传
      // 多个请求，可以用Promise.all
      // Promise.allSettled  es12标准提供的，它的兼容差一些，它可以知道哪些出现了异常
      // Promise.all 只要有一个失败它就是失败，但不知道是哪一个是失败的
      // 浏览器它本身可能对于并发有一些要求,http1.x=>3-5之间，http2.x会更多一些

      // 得到多个请求
      let requests = []
      for (let i = 0; i < partNum; i++) {
        const formData = new FormData()
        formData.append('name', chunkNames[i])
        formData.append('file', chunkFiles[i])
        // const fn = (() => uploadChunkVideoApi(formData))()
        // requests.push(fn)
        requests.push(() => uploadChunkVideoApi(formData))
      }

      // 批量上传
      // try {
      //   await Promise.all(requests)
      //   await delay(1000)
      //   const ret = await mergeVideoApi(hash, extname)
      //   console.log(ret)
      // } catch (error) {
      //   console.log('上传失败')
      // }

      // 请求索引值
      let requestIndex = 0
      const complete = async () => {
        await delay(1000)
        const ret = await mergeVideoApi(hash, extname)
        if (ret.code === 0) {
          this.filmFormData.video = ret.data.path
          this.video = ret.data.url
        }
      }
      const next = async () => {
        if (requests.length <= requestIndex) {
          await complete()
          return
        }
        let ret = await requests[requestIndex++]()
        if (ret.code === 0) {
          next()
        }
      }
      next()

      return false
    },
    // 新增演员
    addActor() {
      if (this.filmFormData.actor.length > 10) {
        this.$message({
          message: '最多添加10个演员',
          type: 'error',
          showClose: true,
          duration: 3000
        })
        return
      }
      this.filmFormData.actor.push({
        value: ''
      })
    },
    // 删除演员
    removeActor(index) {
      this.filmFormData.actor.splice(index, 1)
    },
    // 新增电影表单提交
    submitForm() {
      this.$refs.filmFormRef.validate(async valid => {
        if (valid) {
          let filmData = {
            ...this.filmFormData,
            actor: this.filmFormData.actor.map(item => item.value).join(',')
          }
          console.log(filmData)
        }
      })
    },
    // 重置电影表单提交
    resetForm() {
      this.$refs.filmFormRef.resetFields()
    }
  },
  beforeDestroy() {
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // 组件销毁时，及时销毁编辑器
  }
}
</script>

<style src="@wangeditor/editor/dist/css/style.css"></style>
<style lang="scss" scoped>
.box {
  padding: 10px;
  background: #fff;
  min-height: 100%;
}
</style>
